
#ifndef	GRIDSOLVER_H
#define	GRIDSOLVER_H

#include "Grid.h"
#include "MDPSolver.h"
#include "types.h"
#include "MatlabDrawer.h"

using namespace matlab; 

class MREAgent; 
class TFGenerator; 
class RFGeneralizer; 

namespace GridSolver{

class GridMDPSolver; 


//this class is used for multi-thread planning. the () operator executes VI by constantly selecting a random state 
//and applying bellman backup on it. The termination criterion is set by a GridSolverMaster object
class GridSolverSlave
{
public:
	GridSolverSlave(GridMDPSolver* p){parent = p; }
	void operator()(){doVI();} 
	void doVI();

	GridMDPSolver* parent; 
}; 


class GridMDPSolver 
	: public SlaveableMDPSolver
{
public:
	GridMDPSolver(MREAgent*a, TFGenerator* tf, RFGeneralizer* rf); 
	virtual ~GridMDPSolver(); 
	virtual Action getBestAction(Observation state);
	virtual void	solveModel(Observation currentState); 
	virtual double getStateValue(const Observation o); 
	virtual void operator()(); 
	void init(); 
	State& getStateEX(const StateIndex& si);
	State& getState(Observation o ); 

	void doGeneralization(StateAction& sa, int action,  int ind); 
	
	 

	double getStateValue(StateIndex& si);
	void updatePolicyForState(StateIndex& si);
	int stateIndex2directIndex(const StateIndex& si); 
	Observation stateindex2observation_randomize(const StateIndex& ind); 
	void bringObservation2bound(Observation o); 
	StateIndex observation2stateindex(Observation o); 
	State* states; 
	taskspec_t* taskSpec; 
	int discretized_size [MAX_DIMENSION]; 
	void addToQueue(list<StateIndex>& queue, bool* flags, StateIndex& si); 
	StateIndex directindex2statindex(int ind); 
	void print(); 


	friend class GridSolverSlave; 
	friend class GridSolverMaster; 

private: 
	void doVI(); 
};


class GridMDPForwardSolver: public GridMDPSolver
{
public: 
	GridMDPForwardSolver(MREAgent*a, TFGenerator* tf, RFGeneralizer* rf);
	

	virtual Action getBestAction(Observation state);

protected:
	double getQValue(Observation state, Action a, int horizon); 
	double getStateValue(const Observation state, int horizon); 

}; 


}
#endif
